package cn.ronghuanet.base.service.impl;

import cn.ronghuanet.auth.domain.Permission;
import cn.ronghuanet.auth.mapper.PermissionMapper;
import cn.ronghuanet.base.annotation.RonghuanetPermission;
import cn.ronghuanet.base.service.IAutoScanPermissionService;
import cn.ronghuanet.base.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Service
public class AutoScanPermissionServiceImpl implements IAutoScanPermissionService {

    @Value("${scan.paths}")
    private String paths;
    @Value("${scan.tages}")
    private boolean tages;

    @Autowired
    private PermissionMapper permissionMapper;

    /*
        1.去扫描我整个项目里面的Controller
        2.通过反射获取Controller的Class对象
        3.获取Class对象里面的方法
        4.获取方法上面的注解 @RonghuanetPermission(name = "员工的添加或修改")
        5.配置权限数据
            5.1 先获取类级别的权限 --->数据库里面体现 一条数据[父级]
            5.2 再获取方法级别的权限 --->数据库里面体现 一条数据和自己的Controller父级关联


     */
    @Override
    public void scan() {
        //检查是否需要扫描权限配置
        if(!tages) return;
        //1.获取项目里面需要扫描Controller ---期望得到List<Class>
        /**
         * path :需要扫描的包路径
         */
        List<Class> allControllerClass = ClassUtils.getAllClassName(paths);
        //扫描以后准备存放的父级资源
        List<Permission> permissions =new ArrayList<>();
        //2.循环allControllerClass 得到每一个Controller
        for (Class controllerClass : allControllerClass) {
            //获取Controller上面的注解
            RonghuanetPermission annotation = (RonghuanetPermission) controllerClass.getAnnotation(RonghuanetPermission.class);
            //有可能获取不到 annotation是null  不需要做权限控制
            if (annotation==null) continue;
            Permission parent = new Permission();
            //数据组装
            parent.setName(annotation.name());
            parent.setDescs(annotation.desc());
            RequestMapping requestMapping = (RequestMapping) controllerClass.getAnnotation(RequestMapping.class);
            parent.setUrl(requestMapping.value()[0]);
            parent.setSn(controllerClass.getSimpleName());
            permissions.add(parent);
            //检查父级菜单数据库是否已经有数据   没有就添加 否则就修改
            Permission permission =  permissionMapper.queryBySn(parent.getSn());
            if (permission!=null){
                parent.setId(permission.getId());
                permissionMapper.update(parent);
            }else {
                permissionMapper.save(parent);
            }
            //解决子级资源菜单
            //获取Controller里面所有的方法
            Method[] methods = controllerClass.getMethods();
            for (Method method : methods) {
                //获取添加了RonghuanetPermission注解的方法 --这些方法就是要做权限控制
                RonghuanetPermission annoInMethod = method.getAnnotation(RonghuanetPermission.class);
                if (annoInMethod==null) continue;
                //针对添加了权限注解的方法  生成权限资源数据
                Permission child = new Permission();
                child.setName(annoInMethod.name());
                child.setDescs(annoInMethod.desc());
                //类名:方法名
                child.setSn(parent.getSn()+":"+method.getName());
                child.setParentId(parent.getId());
                /*
                    方法上面添加的注解有多种
                 */
                String childUrl = getChildUrl(method);
                child.setUrl(parent.getUrl()+childUrl);
                Permission childInDb =  permissionMapper.queryBySn(child.getSn());
                if (childInDb!=null){
                    child.setId(childInDb.getId());
                    permissionMapper.update(child);
                }else {
                    permissionMapper.save(child);
                }
            }

        }

    }


    private String getChildUrl(Method method){

        RequestMapping annotation = method.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            return annotation.value().length>0?annotation.value()[0]:"";
        }

        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping!=null){
            return getMapping.value().length>0?getMapping.value()[0]:"";
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping!=null){
            return putMapping.value().length>0?putMapping.value()[0]:"";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping!=null){
            return deleteMapping.value().length>0?deleteMapping.value()[0]:"";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping!=null){
            return postMapping.value().length>0?postMapping.value()[0]:"";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping!=null){
            return patchMapping.value().length>0?patchMapping.value()[0]:"";
        }
        return "";
    }
}
